package com.liujun.security.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.liujun.security.entity.SysUser;
import com.liujun.security.utils.JwtUtil;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * 登录过滤器 处理登录请求的(推荐自己实现,我这里用Filter实现登录)
 *
 * @author pc
 */
public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {


    private AuthenticationManager authenticationManager;
    private RsaKeyProperties prop;

    private PasswordEncoder passwordEncoder;


    public JwtLoginFilter(AuthenticationManager authenticationManager, RsaKeyProperties prop, PasswordEncoder passwordEncoder) {
        this.authenticationManager = authenticationManager;
        this.prop = prop;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        //获取请求体中的username password
        try {
            SysUser sysUser = new ObjectMapper().readValue(request.getInputStream(), SysUser.class);
            //这里传入未加密的密码(切记)
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(sysUser.getUsername(), sysUser.getPassword());
            Authentication authenticate = authenticationManager.authenticate(authRequest);

            return authenticate;
        } catch (IOException e) {
            try {
                //处理失败请求
                response.setContentType("application/json;charset=utf-8");
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                PrintWriter out = response.getWriter();
                Map map = new HashMap<>(2);
                map.put("code", HttpServletResponse.SC_UNAUTHORIZED);
                map.put("msg", "用户名或者密码错误");
                out.write(new ObjectMapper().writeValueAsString(map));
                out.flush();
                out.close();
            } catch (Exception e1) {
                e1.printStackTrace();
            }
            throw new RuntimeException(e);
        }
    }

    /**
     * 授权成功操作----返回token凭证
     *
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        System.out.println("登录成功");
        SysUser resultUser = new SysUser();
        SysUser authUser = (SysUser) authResult.getPrincipal();
        resultUser.setUsername(authUser.getUsername());
        resultUser.setId(authUser.getId());
        resultUser.setStatus(authUser.getStatus());
        resultUser.setSimpleGrantedAuthorities(authUser.getSimpleGrantedAuthorities());
        String token = JwtUtil.generateTokenExpireInMinutes(resultUser, prop.getPrivateKey(), 3600 * 24);
        //将token写入header
        response.addHeader("Authorization", "Bearer " + token);

        PrintWriter out = response.getWriter();
        Map map = new HashMap<>(2);
        map.put("code", HttpServletResponse.SC_OK);
        map.put("msg", "登录成功");
        out.flush();
        out.close();
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {

        System.out.println("登录失败");

        super.unsuccessfulAuthentication(request, response, failed);
    }
}
